#include "sm2_operation.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>

/**
 * @brief   char_to_hex子例程，将一个8个字符长度的十六进制字符串转换为一个32位无符号整数。
 * 
 * @details 此函数接收一个长度为8的十六进制字符串，将其逐个字符解析并转换为对应的32位无符号整数。支持大小写十六进制字符。
 * 
 * @param[in]  hex_block  长度为8的十六进制字符串
 * 
 * @return 转换后的32位无符号整数
 * 
 * @note    如果输入的字符串包含非法字符（即不是0-9、a-f或A-F之间的字符），函数会输出错误信息并终止程序。
 * @warning 输入字符串长度必须为8，否则会导致逻辑错误。
 * @pre     无
 * @post    返回32位无符号整数，表示8个十六进制字符转换后的结果。
 */
static uint32_t parse_char_to_hex_block(const char *hex_block)
{
    uint32_t result = 0;
    uint32_t t = 0;
    for(int i = 0; i < 7; ++i) {
        if(hex_block[i] >= '0' && hex_block[i] <= '9')  result |= (uint32_t)(hex_block[i] - '0');
        else if (hex_block[i] >= 'a' && hex_block[i] <= 'f') result |= (uint32_t)(hex_block[i] - 'a' + 10);
        else if (hex_block[i] >= 'A' && hex_block[i] <= 'F') result |= (uint32_t)(hex_block[i] - 'A' + 10); 
        else {
            fprintf(stderr, "ERROR：处理字符串转整型子例程出错，参数不是16进制表示");
            exit(-1);
        }
        result <<= 4;
    }
    if(hex_block[7] >= '0' && hex_block[7] <= '9')  result |= (uint32_t)(hex_block[7] - '0');
    else if (hex_block[7] >= 'a' && hex_block[7] <= 'f') result |= (uint32_t)(hex_block[7] - 'a' + 10);
    else if (hex_block[7] >= 'A' && hex_block[7] <= 'F') result |= (uint32_t)(hex_block[7] - 'A' + 10); 
    return result;
}

/**
 * @brief   将一个长度为64的十六进制字符串转换为 `sm2_uint256_t` 类型的数值。
 * 
 * @details 此函数将传入的长度为64的十六进制字符串按每8个字符转换为一个32位无符号整数，并填充到 `sm2_uint256_t` 类型的数组中。 
 *          如果输入字符串长度大于64或小于64，则会终止程序并输出错误信息。
 * 
 * @param[out]  result  目标存储数组，转换结果将被存入其中
 * @param[in]   hex_block  长度为64的十六进制字符串
 * 
 * @return 无返回值
 * 
 * @note    此函数目前仅支持64长度的十六进制字符串。如果输入长度不是64，会终止程序并输出错误信息。
 * @warning 输入字符串长度必须严格为64，否则会导致溢出或处理错误。
 * @pre     无
 * @post    `result` 数组中的每个元素将被填充为转换后的32位整数。
 */
void char_to_hex(sm2_uint256_t result, const char *hex_block)
{
    uint32_t len = strlen(hex_block);
    int i = 0;
    if(len > 64) {
        fprintf(stderr, "ERROR: 处理字符串转整型时出错，字符串长度大于64，存在溢出风险");
        exit(-1); // 存在溢出风险
    }
    if(len < 64) {
        fprintf(stderr, "ERROR：暂时没有实现长度小于64字节的字符串处理功能，需要手动补上0");
        exit(-1);
    }

    for(i = 7; i >= 0; --i)
    {
        result[7-i] = parse_char_to_hex_block(hex_block+(i*8));
    }
}


/**
 * @brief   将一个32位无符号整数转换为8个十六进制字符并填充到字符串中指定位置。
 * 
 * @details 此函数接收一个32位无符号整数，将其按位拆分为4个十六进制数字（共8个字符），并将其转换为字符形式，
 *          然后将字符存入目标字符串的指定位置。
 * 
 * @param[out]  result  目标字符串，转换后的十六进制字符将被存入其中
 * @param[in]   s       目标字符串的起始索引位置
 * @param[in]   e       目标字符串的结束索引位置
 * @param[in]   _n      需要转换的32位无符号整数
 * 
 * @return 无返回值
 * 
 * @note    此函数假设输入的 `s` 和 `e` 为合法索引，并且确保转换的单位必须是8个字符。
 * @warning `s` 和 `e` 之间的长度必须为8，否则会导致错误。
 * @pre     无
 * @post    目标字符串 `result` 从索引 `s` 到 `e` 被填充为对应的十六进制字符。
 */
static void parse_hex_to_char_block(char *result, int s, int e, uint32_t _n)
{
    int i = 0;
    if(e-s+1 != 8) {
        fprintf(stderr, "ERROR：处理整型转字符串的子例程，处理的单位必须是8");
        exit(-1);
    }

    for(i = e; i >= s; --i) {
        if((_n & (uint32_t)0xf) < 10) result[i] = (char)(_n & (uint32_t)0xf) + '0';
        else result[i] = (char)((_n & (uint32_t)0xf)-10) + 'a';
        _n >>= 4;
    }
}

/**
 * @brief   将 `sm2_uint256_t` 类型的数值转换为对应的十六进制字符串。
 * 
 * @details 此函数将 `sm2_uint256_t` 类型的数值转换为长度为64的十六进制字符串。每个32位元素被转化为8个十六进制字符， 
 *          最终的字符串会包含完整的64个十六进制字符（不含前缀）。
 * 
 * @param[in]   n  需要转换为十六进制字符串的 `sm2_uint256_t` 类型数值
 * 
 * @return 返回转换后的十六进制字符串（长度为64）
 * 
 * @note    返回的字符串是动态分配的内存，调用者需要负责释放该内存。
 * @warning 输入的 `n` 必须是合法的 `sm2_uint256_t` 数值。
 * @pre     无
 * @post    返回的字符串包含64个十六进制字符，表示输入的256位数值。
 */
char *hex_to_char(sm2_uint256_t n)
{
    char *hex_block = malloc(65);
    memset(hex_block, 0, 65);
    int i = 0;

    for(i = 7; i >= 0; --i) {
        parse_hex_to_char_block(hex_block, i*8, i*8+7, n[7-i]);
    }

    return hex_block;
}

/**
 * @brief   将256位整数转化为32个字节数组
 * 
 * @details 将256位整形转化为32个字节的数组
 * 
 * @param[out]  out  目标32字节数组
 * @param[in]   num  源256位整数
 * 
 * @return 无返回值
 * 
 * @note    无
 * @warning 无
 * @pre     无
 * @post    无
 */
void sm2_integer_to_bytes(uint8_t out[32], sm2_uint256_t num)
{
    int i=0, j=31;
    while(i < 8){
        out[j--] = (uint8_t)num[i];
        out[j--] = (uint8_t)(num[i] >> 8);
        out[j--] = (uint8_t)(num[i] >> 16);
        out[j--] = (uint8_t)(num[i] >> 24);
        i++;
    }
}

void sm2_bytes_to_integer(sm2_uint256_t num, uint8_t a[32]) 
{
    sm2_set_zero(num);
    int i = 7, j = 0;
    while(i >= 0) {
        num[i] |= ((uint32_t)a[j++]) << 24; //| ((uint32_t)a[j++]) << 16 | ((uint32_t)a[j++]) << 8 | ((uint32_t)a[j++]);
        num[i] |= ((uint32_t)a[j++]) << 16;
        num[i] |= ((uint32_t)a[j++]) << 8;
        num[i] |= ((uint32_t)a[j++]);
        i--;
    }
}

int sm2_bytes_compare(const uint8_t a[32], const uint8_t b[32])
{
    for(int i=0; i<32; i++){
        if(a[i] != b[i]) return 1;
    }
    return 0;
}

void convert_message_to_bytes(uint8_t *result, char *a)
{
    if(!result || !a) return;
    size_t len = strlen(a);
    if(len & 1 || len == 0) return;
    while(len > 0){
        *result++ = *a++;
        len--;
    }
}

int hex_char_to_value(char c) {
    if (isdigit(c)) {
        return c - '0';
    } else if (c >= 'a' && c <= 'f') {
        return c - 'a' + 10;
    } else if (c >= 'A' && c <= 'F') {
        return c - 'A' + 10;
    }
    return -1;  // 如果不是合法的十六进制字符，返回 -1表示错误
}

void convert_hex_message_to_bytes(uint8_t *result, const char *a)
{
    if(!result || !a) return;
    size_t len = strlen(a);
    if(len & 1 || len == 0) return;
    uint8_t tmp;
    while(len > 0){
        tmp = hex_char_to_value(*a++);
        *result++ = (tmp << 4) + hex_char_to_value(*a++);
        len-=2;
    }
}

/* 警告： 一定要确保result开放了足够的空间 */
void convert_bytes_to_hex_message(char *result, const uint8_t *a, const size_t n)
{
    int i = 0;
    uint8_t h = 0, l = 0;
    for(i = 0; i < n; ++i) {
        h = a[i] >> 4;
        l = a[i] & 0xf;
        if(h >= 0 && h <= 9) result[i*2] = h + '0';
        else if(h >= 9 && h <= 15) result[i*2] = (h-10) + 'A';
        else fprintf(stderr, "转换字节串到16进制字面值出错\n");

        if(l >= 0 && l <= 9) result[i*2+1] = (char)l + '0';
        else if(l >= 9 && l <= 15) result[i*2+1] = (char)(l-10) + 'A';
        else fprintf(stderr, "转换字节串到16进制字面值出错\n");
    }   
    result[i*2] = '\0';
}

// #define SM2_FORMAT_DEBUG
#if defined SM2_FORMAT_DEBUG
int main(void)
{
    char *message = "BF7224726BCF102DF855915246B113655B3976F4D2A4D8497A14ADD50D82F29C";
    uint8_t *result = malloc(strlen(message)/2+1);
    convert_hex_message_to_bytes(result, message);
    while(*result!=0) {
        printf("%02x ", (uint8_t)*result);
        result += 1;
    }
    
}
#endif
